/*! \file pres_parser_test.cc
 *
 * \brief Test file for parsing sets and relations from an omega-like syntax.
 *
 * \date Started: 5/17/2010
 * \date Last Modified: 6/28/2010
 * \authors Michelle Strout, Alan LaMielle, Nicholas Jeanette
 *
 * Copyright (c) 2010, Colorado State University <br>
 * All rights reserved. <br>
 * See ../../COPYING for details. <br>
*/



#include <gtest/gtest.h>
#include <string>
#include <iegenlib/iegenlib.h>
#include <iostream>

using namespace iegenlib;

//The most basic set test we are comparing our string with the string produced
//by the omega syntax visitor. NOTE: OmegaSyntax
TEST(PresParser, SimpVar) {

   std::string temp="{[]}";

   PresSet *PS = pres_parser::parse_set(temp);
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}


TEST(PresParser, SimpVar2) {

   std::string temp="{[x]}";

   PresSet *PS = pres_parser::parse_set(temp);
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimpVar3) {

   std::string temp="{[x,y]}";

   PresSet *PS = pres_parser::parse_set(temp);
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

//Test case dealing with equalities these are converted eg x=10 -> x-10=0
//by the omegasyntax so the string temp passed in must be tweeked before
//compared with the generated omega string.
TEST(PresParser, SimpSet) {

   std::string temp="{[x]:x=10}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[x]:x-10=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

//Test case dealing with inequalities these are converted always to >=
//by the omegasyntax so the string temp passed in must be tweeked
//before compared with the generated omega string.
TEST(PresParser, SimpSet2) {

   std::string temp="{[x]:x<10 and x>0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[x]:-x+9>=0 and x-1>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSet) {

   std::string temp="{[x,y]:x<y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[x,y]:y-x-1>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSet2) {

   std::string temp="{[x,y]:x<y and x>=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[x,y]:y-x-1>=0 and x>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSet3) {

   std::string temp="{[x,y]:x=y && x>=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[x,y]:x-y=0 and x>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSet4) {

   std::string temp="{[5,y]:x=y && x>=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[5,y]:x-y=0 and x>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSet6) {

   std::string temp="{[x,4]:x=y && x>=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[x,4]:x-y=0 and x>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSetLowAnd) {

   std::string temp="{[x,y]:x<y and x>=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[x,y]:y-x-1>=0 and x>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSetBigAnd) {

   std::string temp="{[x,y]:x=y AND x>=4}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[x,y]:x-y=0 and x-4>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}



TEST(PresParser, ThreeVarSet) {

   std::string temp="{[x,y,z]:x=y and x>z and y<100 and y=z}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[x,y,z]:x-y=0 and x-z-1>=0 and -y+99>=0 and y-z=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}


TEST(PresParser, SimExpUDash) {

   std::string temp = "{[x,y]:x=-y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:x+y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimExpUDash2) {

   std::string temp = "{[x]:x=-8}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x]:x+8=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimExpDash) {

   std::string temp = "{[x,y]:x-y=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:x-y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimExpDash2) {

   std::string temp = "{[x]:x-8=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x]:x-8=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimExpAdd) {

   std::string temp = "{[x,y]:x+y=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:x+y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimExpAdd2) {

   std::string temp = "{[x]:x+8=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x]:x+8=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimExpMul2) {

   std::string temp = "{[x]:x*8=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x]:8x=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSetWithAdd) {

   std::string temp="{[x,y]:(x+5)<y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp="{[x,y]:y-x-6>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSetWithDash) {

   std::string temp = "{[x,y]:x=(y-4)}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:x-y+4=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSetWithTimes) {

   std::string temp = "{[x,y]:x=(y*4) and x>=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:x-4y=0 and x>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSetWithIntMulId) {

   std::string temp = "{[x,y]:x<=4y and x>=5}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:4y-x>=0 and x-5>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSetWithIntMulIdPar) {

   std::string temp = "{[x,y]:x=4(y) and x>=9}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:x-4y=0 and x-9>=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSetWithIntMulPlus) {

   std::string temp = "{[x,y]:x=6(y+4)}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:x-6y-24=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, TwoVarSetWithIntMulDash) {

   std::string temp = "{[x,y]:x=6(y-4)}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:x-6y+24=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimSetWithIntMulId) {

   std::string temp = "{[x,y]:x=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:x-4y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimSetWithFunc) {

   std::string temp = "{[x,y]:f(x,y)=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:f(x,y)-4y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimSetWithFuncSingle) {

   std::string temp = "{[x,y]:f(x)=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:f(x)-4y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimSetWithFunc2) {

   std::string temp = "{[x,y]:f(3x+y,z)=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:f(3x+y,z)-4y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimSetWithFunc31) {

   std::string temp = "{[x,y,z]:f(3x+y,z)=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y,z]:f(3x+y,z)-4y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}


TEST(PresParser, SimSetWithParNum) {

   std::string temp = "{[x,y]:(5)=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:-4y+5=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimSetWithParId) {

   std::string temp = "{[x,y]:(z)=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:z-4y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimSetWithParNumMulId) {

   std::string temp = "{[x,y]:(5z)=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:5z-4y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimSetWithParIdAddId) {

   std::string temp = "{[x,y]:(z+x)=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:z+x-4y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimSetWithParIdAddNum) {

   std::string temp = "{[x,y]:(z+4)=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:z-4y+4=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

TEST(PresParser, SimSetWithParUnId) {

   std::string temp = "{[x,y]:(-z)=4y}";

   PresSet *PS = pres_parser::parse_set(temp);
   temp = "{[x,y]:-z-4y=0}";
   OmegaSyntax omega;
   PS->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PS;
}

//This is one of Alan's original test cases.
//Collection of set strings are placed into the test_str array and
//the string that should be created by the omega syntax visitor is res_str.
TEST(PresParser, alanSet){

   //this is an array of strings to be tested as relations
   std::string test_str[] = {
        "{[]}",
        "{[a]}",
        "{[a,b]}",
        "{[a,b,c]}",
        "{[]:6=7}",
        "{[a]:6=7}",
        "{[a,b]:6=7}",
        "{[a,b,c]:6=7}",
        "{[]:6=7}",
        "{[a]:6=7}",
        "{[a,b]:6=7}",
        "{[a,b,c]:6=7}",
        "{[a,b]:a=1}",
        "{[a,b]:b=1}",
        "{[a,b]:a'=1}",
        "{[a,b]:b'=1}",
        "{[a,b]:a=b}",
        "{[a,b]:a'=b'}",
        "{[a,b]:a=a' and b=b'}",
        "{[a,b]:a=b' and b=a'}",
        "{[a,b]:a=b and a=a' and a'=b'}",
        "{[a,b]: a=b && a=a' and a'=b' && a=1}",
        "{[a,b]: 1<=a and a<=b && b<=10}",
        "{[a,b]: a>=b && c>=d AND a=b}",
        "{[ii]: ii>=f(x)}",
        "{[a]:f(a,a)>=0}",
        "{[a]:f(g(a,a))>=0}",
        "{[a]:3f(5*g(2a,-5*a)-5)>=0}",
        "{[a,b]: a>=3 && b>=12; [a,b]: a>5 && b<=9}", //added test case for isl Union format
        "{[a]: a>=3; [b]: b>=5}", //added test case for isl Union format
        "{[a,b]: a>=5 && b>=10} union {[a,d]: a>4 && d<=15} union {[b,c]: b<=12 && c>=7}", //added test case for omega Union format
        "[a,b] -> {[a,b]: a>=5 && b>=10}", // added test case for symbolics with set
        "[w,x] -> {[a,b]: a>=5 && b>=10} union {[a,d]: a>4 && d<=15}", // added test case for symbolics with set Omega syntax
        "[w,x] -> {[a,b]: a>=5 && b>=10; [a,d]: a>4 && d<=15}", // added test case for symbolics with set Isl syntax
        "{[a]: exists(b: a=b)}",
        "{[a]: exists (b : a=b )}",
        "{[a]: exists(b,c,d: a=b)}",
        "{[a,b]: exists(c,d: a=b)}"
   };

   //puts test_str into a list called test1
   list<std::string> test1 (test_str, test_str + sizeof(test_str) / sizeof(std::string) );

   //this is an array of strings that should match up with the test
   //strings however these are now in omegasyntax
   std::string res_str[] = {
        "{[]}",
        "{[a]}",
        "{[a,b]}",
        "{[a,b,c]}",
        "{[]:-1=0}",
        "{[a]:-1=0}",
        "{[a,b]:-1=0}",
        "{[a,b,c]:-1=0}",
        "{[]:-1=0}",
        "{[a]:-1=0}",
        "{[a,b]:-1=0}",
        "{[a,b,c]:-1=0}",
        "{[a,b]:a-1=0}",
        "{[a,b]:b-1=0}",
        "{[a,b]:a'-1=0}",
        "{[a,b]:b'-1=0}",
        "{[a,b]:a-b=0}",
        "{[a,b]:a'-b'=0}",
        "{[a,b]:a-a'=0 and b-b'=0}",
        "{[a,b]:a-b'=0 and b-a'=0}",
        "{[a,b]:a-b=0 and a-a'=0 and a'-b'=0}",
        "{[a,b]:a-b=0 and a-a'=0 and a'-b'=0 and a-1=0}",
        "{[a,b]:a-1>=0 and b-a>=0 and -b+10>=0}",
        "{[a,b]:a-b>=0 and c-d>=0 and a-b=0}",
        "{[ii]:ii-f(x)>=0}",
        "{[a]:f(a,a)>=0}",
        "{[a]:f(g(a,a))>=0}",
        "{[a]:3f(5g(2a,-5a)-5)>=0}",
        "{[a,b]:a-6>=0 and -b+9>=0; [a,b]:a-3>=0 and b-12>=0}",
        "{[b]:b-5>=0; [a]:a-3>=0}",
        "{[a,b]:a-5>=0 and b-10>=0; [a,d]:a-5>=0 and -d+15>=0; [b,c]:-b+12>=0 and c-7>=0}",
        "[b,a]->{[a,b]:a-5>=0 and b-10>=0}",
        "[x,w]->{[a,b]:a-5>=0 and b-10>=0; [a,d]:a-5>=0 and -d+15>=0}",
        "[x,w]->{[a,d]:a-5>=0 and -d+15>=0; [a,b]:a-5>=0 and b-10>=0}",
        "{[a]:a-b=0}",
        "{[a]:a-b=0}",
        "{[a]:a-b=0}",
        "{[a,b]:a-b=0}"
   };

   //puts res_str into a list called res1
   list<std::string> res1 (res_str, res_str + sizeof(res_str) / sizeof(std::string) );

    //creates our iterator for the res1 list
   list<std::string>::iterator itr = res1.begin();

   //loops through as long as there is something in the test1 list
   //grab the string at the location and insert it into the parser
   //compare that string with the string at the same location in the res list
   //note that both lists are same size
   for (list<std::string>::iterator it = test1.begin(); it != test1.end(); it++){

      //temp is the test string tres is the res string
      std::string temp = *it;
      std::string tres = *itr;
      PresSet *PS = pres_parser::parse_set(temp);
      OmegaSyntax omega;
      PS->apply(&omega);
      EXPECT_EQ(omega.getOmega(),tres);
      itr++;
      delete PS;
   }
}


//// test cases for isl and Omega Union format with sets
TEST(PresParser, UnionSets){

   //this is an array of strings to be tested as relations
   std::string test_str[] = {
        "{[a,b]: a>=3 && b>=12; [a,b]: a>5 && b<=9}", //added test case for isl Union format
        "{[a]: a>=3; [b]: b>=5}", //added test case for isl Union format
        "{[a,b]: a>=5 && b>=10} union {[a,d]: a>4 && d<=15} union {[b,c]: b<=12 && c>=7}", //added test case for omega Union format
   };

   //puts test_str into a list called test1
   list<std::string> test1 (test_str, test_str + sizeof(test_str) / sizeof(std::string) );

   //this is an array of strings that should match up with the test
   //strings however these are now in omegasyntax
   std::string res_str[] = {
        "{[a,b]:a-6>=0 and -b+9>=0; [a,b]:a-3>=0 and b-12>=0}",
        "{[b]:b-5>=0; [a]:a-3>=0}",
        "{[a,b]:a-5>=0 and b-10>=0; [a,d]:a-5>=0 and -d+15>=0; [b,c]:-b+12>=0 and c-7>=0}",
   };

   //puts res_str into a list called res1
   list<std::string> res1 (res_str, res_str + sizeof(res_str) / sizeof(std::string) );

    //creates our iterator for the res1 list
   list<std::string>::iterator itr = res1.begin();

   //loops through as long as there is something in the test1 list
   //grab the string at the location and insert it into the parser
   //compare that string with the string at the same location in the res list
   //note that both lists are same size
   for (list<std::string>::iterator it = test1.begin(); it != test1.end(); it++){

      //temp is the test string tres is the res string
      std::string temp = *it;
      std::string tres = *itr;
      PresSet *PS = pres_parser::parse_set(temp);
      OmegaSyntax omega;
      PS->apply(&omega);
      EXPECT_EQ(omega.getOmega(),tres);
      itr++;
      delete PS;
   }
}


//// test cases for isl symbolic syntax with sets
TEST(PresParser, ISL_SymbolicSets){

   //this is an array of strings to be tested as relations
   std::string test_str[] = {
        "[a,b] -> {[a,b]: a>=5 && b>=10}", // added test case for symbolics with set
        "[w,x] -> {[a,b]: a>=5 && b>=10} union {[a,d]: a>4 && d<=15}", // added test case for symbolics with set Omega syntax
        "[w,x] -> {[a,b]: a>=5 && b>=10; [a,d]: a>4 && d<=15}" // added test case for symbolics with set Isl syntax
   };

   //puts test_str into a list called test1
   list<std::string> test1 (test_str, test_str + sizeof(test_str) / sizeof(std::string) );

   //this is an array of strings that should match up with the test
   //strings however these are now in omegasyntax
   std::string res_str[] = {
        "[b,a]->{[a,b]:a-5>=0 and b-10>=0}",
        "[x,w]->{[a,b]:a-5>=0 and b-10>=0; [a,d]:a-5>=0 and -d+15>=0}",
        "[x,w]->{[a,d]:a-5>=0 and -d+15>=0; [a,b]:a-5>=0 and b-10>=0}"
   };

   //puts res_str into a list called res1
   list<std::string> res1 (res_str, res_str + sizeof(res_str) / sizeof(std::string) );

    //creates our iterator for the res1 list
   list<std::string>::iterator itr = res1.begin();

   //loops through as long as there is something in the test1 list
   //grab the string at the location and insert it into the parser
   //compare that string with the string at the same location in the res list
   //note that both lists are same size
   for (list<std::string>::iterator it = test1.begin(); it != test1.end(); it++){

      //temp is the test string tres is the res string
      std::string temp = *it;
      std::string tres = *itr;
      PresSet *PS = pres_parser::parse_set(temp);
      OmegaSyntax omega;
      PS->apply(&omega);
      EXPECT_EQ(omega.getOmega(),tres);
      itr++;
      delete PS;
   }
}


//simple relation testing the -> symbol
TEST(PresParser, Relation) {

   std::string temp = "{[]->[]}";

   PresRelation *PR = pres_parser::parse_relation(temp);
   OmegaSyntax omega;
   PR->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PR;
}

//simple relation with single var
TEST(PresParser, Relation2) {

   std::string temp = "{[x]->[y]}";

   PresRelation *PR = pres_parser::parse_relation(temp);
   OmegaSyntax omega;
   PR->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);;
   delete PR;
}

//relation testing multiple vars
TEST(PresParser, Relation3) {

   std::string temp = "{[x,y]->[x,y]}";

   PresRelation *PR = pres_parser::parse_relation(temp);
   OmegaSyntax omega;
   PR->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PR;
}

//relation with two vars and a lt eq and
TEST(PresParser, Relation4) {

   std::string temp = "{[x,y]->[x,y]:y=0 and x<y}";

   PresRelation *PR = pres_parser::parse_relation(temp);
   temp = "{[x,y]->[x,y]:y=0 and y-x-1>=0}";
   OmegaSyntax omega;
   PR->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PR;
}

TEST(PresParser, Relation5) {

   std::string temp = "{[x,z]->[x,z]:z=0 and x<z}";
   PresRelation *PR = pres_parser::parse_relation(temp);
   temp = "{[x,z]->[x,z]:z=0 and z-x-1>=0}";
   OmegaSyntax omega;
   PR->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PR;
}

TEST(PresParser, SemicolonUnionRelation6) {

   std::string temp = "{[x,z]->[x,z]:z=0 and x<z; [x,z]->[x,z]:z=0 and x<z}";
   PresRelation *PR = pres_parser::parse_relation(temp);
   temp = "{[x,z]->[x,z]:z=0 and z-x-1>=0; [x,z]->[x,z]:z=0 and z-x-1>=0}";
   OmegaSyntax omega;
   PR->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PR;
}

TEST(PresParser, SemicolonUnionRelation7) {

   std::string temp = "{[x,z]->[x,z]:z=0 and x<z; [x,z]->[x,z]:z=0 and x<z; [x,z]->[x,z]:x>z and z>=2}";
   PresRelation *PR = pres_parser::parse_relation(temp);
   temp = "{[x,z]->[x,z]:x-z-1>=0 and z-2>=0; [x,z]->[x,z]:z=0 and z-x-1>=0; [x,z]->[x,z]:z=0 and z-x-1>=0}";
   OmegaSyntax omega;
   PR->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PR;
}

TEST(PresParser, ISL_SymbolicRelation8) {

   std::string temp = "[x,y] -> {[x,z]->[x,z]:z=0 and x<z; [x,z]->[x,z]:z=0 and x<z; [x,z]->[x,z]:x>z and z>=2}";
   PresRelation *PR = pres_parser::parse_relation(temp);
   temp = "[y,x]->{[x,z]->[x,z]:x-z-1>=0 and z-2>=0; [x,z]->[x,z]:z=0 and z-x-1>=0; [x,z]->[x,z]:z=0 and z-x-1>=0}";
   OmegaSyntax omega;
   PR->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PR;
}

TEST(PresParser, OmegaUnionRelation9) {

   std::string temp = "[x,y] -> {[x,z]->[x,z]:z=0 and x<z} union {[x,z]->[x,z]:z=0 and x<z} union {[x,z]->[x,z]:x>z and z>=2}";
   PresRelation *PR = pres_parser::parse_relation(temp);
   temp = "[y,x]->{[x,z]->[x,z]:z=0 and z-x-1>=0; [x,z]->[x,z]:z=0 and z-x-1>=0; [x,z]->[x,z]:x-z-1>=0 and z-2>=0}";
   OmegaSyntax omega;
   PR->apply(&omega);
   EXPECT_EQ(omega.getOmega(),temp);
   delete PR;
}

//This is one of Alan's original test cases.
//Collection of relation strings are test_str and the strings that should
//be created by the omega syntax visitor are in res_str.
TEST(PresParser, alanRelation){

   //this is an array of strings to be tested as relations
   std::string test_str[] = {
        "{[]->[]}",
        "{[a]->[]}",
        "{[a,b]->[]}",
        "{[a,b,c]->[]}",
        "{[]->[a']}",
        "{[]->[a',b']}",
        "{[]->[a',b',c']}",
        "{[a]->[a']}",
        "{[a,b]->[a',b']}",
        "{[a,b,c]->[a',b',c']}",
        "{[]->[]:6=7}",
        "{[a]->[]:6=7}",
        "{[a,b]->[]:6=7}",
        "{[a,b,c]->[]:6=7}",
        "{[]->[a']:6=7}",
        "{[]->[a',b']:6=7}",
        "{[]->[a',b',c']:6=7}",
        "{[a]->[a']:6=7}",
        "{[a,b]->[a',b']:6=7}",
        "{[a,b,c]->[a',b',c']:6=7}",
        "{[a,b]->[a',b']: a=1}",
        "{[a,b]->[a',b']: b=1}",
        "{[a,b]->[a',b']: a'=1}",
        "{[a,b]->[a',b']: b'=1}",
        "{[a,b]->[a',b']: a=b}",
        "{[a,b]->[a',b']: a'=b'}",
        "{[a,b]->[a',b']: a=a' && b=b'}",
        "{[a,b]->[a',b']: a=b' && b=a'}",
        "{[a,b]->[a',b']: a=b && a=a' and a'=b'}",
        "{[a,b]->[a',b']: a=b && a=a' and a'=b' && a=1}",
        "{[a,b]->[c,d]: 1<=a and a<=b && b<=10}",
        "{[a,b]->[c,d]: a>=b && c>=d AND a=b}",
        "{[ii] -> [inter_func]: ii>=f(x)}",
        "{[a]->[b]:f(a,a)>=0}",
        "{[a]->[b]:f(g(a,a))>=0}",
        "{[a]->[b]:3f(5*g(2a,-5*a)-5)>=0}",
        "{[a]->[b]: exists(c: a=c)}",
        "{[a]->[b]: exists (c : a=c )}",
        "{[a]->[b]: exists(c,d: a=b)}",
        "{[a,b]->[c]: exists(c,d: a=b)}"
    };

   //puts test_str into a list called test1
   list<std::string> test1 (test_str, test_str + sizeof(test_str) / sizeof(std::string) );

   //this is an array of strings that should match up with the test strings however
   //these are now in omegasyntax
   std::string res_str[] = {
        "{[]->[]}",
        "{[a]->[]}",
        "{[a,b]->[]}",
        "{[a,b,c]->[]}",
        "{[]->[a']}",
        "{[]->[a',b']}",
        "{[]->[a',b',c']}",
        "{[a]->[a']}",
        "{[a,b]->[a',b']}",
        "{[a,b,c]->[a',b',c']}",
        "{[]->[]:-1=0}",
        "{[a]->[]:-1=0}",
        "{[a,b]->[]:-1=0}",
        "{[a,b,c]->[]:-1=0}",
        "{[]->[a']:-1=0}",
        "{[]->[a',b']:-1=0}",
        "{[]->[a',b',c']:-1=0}",
        "{[a]->[a']:-1=0}",
        "{[a,b]->[a',b']:-1=0}",
        "{[a,b,c]->[a',b',c']:-1=0}",
        "{[a,b]->[a',b']:a-1=0}",
        "{[a,b]->[a',b']:b-1=0}",
        "{[a,b]->[a',b']:a'-1=0}",
        "{[a,b]->[a',b']:b'-1=0}",
        "{[a,b]->[a',b']:a-b=0}",
        "{[a,b]->[a',b']:a'-b'=0}",
        "{[a,b]->[a',b']:a-a'=0 and b-b'=0}",
        "{[a,b]->[a',b']:a-b'=0 and b-a'=0}",
        "{[a,b]->[a',b']:a-b=0 and a-a'=0 and a'-b'=0}",
        "{[a,b]->[a',b']:a-b=0 and a-a'=0 and a'-b'=0 and a-1=0}",
        "{[a,b]->[c,d]:a-1>=0 and b-a>=0 and -b+10>=0}",
        "{[a,b]->[c,d]:a-b>=0 and c-d>=0 and a-b=0}",
        "{[ii]->[inter_func]:ii-f(x)>=0}",
        "{[a]->[b]:f(a,a)>=0}",
        "{[a]->[b]:f(g(a,a))>=0}",
        "{[a]->[b]:3f(5g(2a,-5a)-5)>=0}",
        "{[a]->[b]:a-c=0}",
        "{[a]->[b]:a-c=0}",
        "{[a]->[b]:a-b=0}",
        "{[a,b]->[c]:a-b=0}"
    };

   //puts res_str into a list called res1
   list<std::string> res1 (res_str, res_str + sizeof(res_str) / sizeof(std::string) );

   //creates our iterator for the res1 list
   list<std::string>::iterator itr = res1.begin();

   //loops through as long as there is something in the test1 list
   //grab the string at the location and insert it into the parser
   //compare that string with the string at the same location in the res list
   //note that both lists are same size
   for (list<std::string>::iterator it = test1.begin(); it != test1.end(); it++){

      //temp is the test string tres is the res string
      std::string temp = *it;
      std::string tres = *itr;
      PresRelation *PR = pres_parser::parse_relation(temp);
      OmegaSyntax omega;
      PR->apply(&omega);
      EXPECT_EQ(omega.getOmega(),tres);
      itr++;
      delete PR;
   }
}

// Error test cases
// These should fail if the parse does not return null

//missing variable or extra , for relation
TEST(PresParser, FAIL) {

   std::string temp = "{[x,]->[x,y]:y=0 and x<y}";
   try{
      PresRelation *PR = pres_parser::parse_relation(temp);
      if(PR!=NULL){
         EXPECT_EQ(1,2);
      }
   }catch(string s){
      //std::cerr << s;
   }
}

//missing variable or extra , for set
TEST(PresParser, FAIL3) {

   std::string temp = "{[x,]:y=0 and x<y}";

   try{
      PresSet *PS = pres_parser::parse_set(temp);
      if(PS!=NULL){
         EXPECT_EQ(1,2);
      }
   }catch(string s){
      //std::cerr << s;
   }

}

//function is missing )
TEST(PresParser, FailFunc) {

   std::string temp = "{[x,y]:f(y=0 and x<y}";
   try{
      PresSet *PS = pres_parser::parse_set(temp);
      if(PS!=NULL){
         EXPECT_EQ(1,2);
      }
   }catch(string s){
      //std::cerr << s;
   }
}



//set being passed to a relation
TEST(PresParser, notRelation) {

   std::string temp = "{[x]:y=0 and x<y}";

   PresRelation *PR = pres_parser::parse_relation(temp);
   //temp = "{[x,y]->[x,y]:y=0 and y-x-1>=0}";
   if(PR!=NULL){
      EXPECT_EQ(1,2);
   }
   delete PR;
}

//bad function list or extra ,
TEST(PresParser, memissue2) {

   std::string temp = "{[x]:y=0 and F(x<y,)}";
   try{
      PresSet *PS = pres_parser::parse_set(temp);
      //temp = "{[x,y]->[x,y]:y=0 and y-x-1>=0}";
      if(PS!=NULL){
         EXPECT_EQ(1,2);
      }
      delete PS;
   }catch(string s){
      //std::cerr << s;
   }
}

//relation missing - of ->
TEST(PresParser, failrelation) {

   std::string temp = "{[x]>[4]:y=0 and x<y}";

   try{
      PresRelation *PR = pres_parser::parse_relation(temp);
      //temp = "{[x,y]->[x,y]:y=0 and y-x-1>=0}";
      if(PR!=NULL){
         std::cout << "never ever here" << std::endl;
               temp = "{[x]->[4]:y=0 and y-x-1>=0}";
         OmegaSyntax omega;
         PR->apply(&omega);
         EXPECT_EQ(omega.getOmega(),temp);
         delete PR;
      }
   }catch(string s){
      //std::cerr << s;
   }
}

/*
//not legal PS should be null
TEST(PresParser, SimExpMul) {

   std::string temp = "{[x,a]:z*w=0}";

   PresSet *PS = pres_parser::parse_set(temp);
   if(PS!=NULL){
      EXPECT_EQ(1,2);
   }
}
*/

